<?php

namespace apiend\models\searchs;

use Yii;
use yii\db\Expression;
use yii\helpers\Inflector;
use common\helpers\StringHelper;
use common\models\shop\ShopOrderRefund;

/**
 * 订单检索信息模型
 * 
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class OrderBaseSearch extends \common\models\shop\ShopOrder {

    /**
     * @var string 查询类型
     */
    public $type;

    /**
     * @var string 查询类型
     */
    public $keytype;

    /**
     * @var string 关键词
     */
    public $keyword;

    /**
     * @var string 时间区间
     */
    public $datetimes;

    /**
     * @var string 结算类型
     */
    public $settle_status;

    /**
     * @var string 促销类型
     */
    public $promotion;

    /**
     * @var string 支付方式
     */
    public $paymodes;

    /**
     * @var array 排序
     */
    public $sort = [
        'defaultOrder' => [
            'pay_time' => SORT_DESC,
            'created_at' => SORT_DESC,
            'updated_at' => SORT_DESC,
        ]
    ];

    /**
     * {@inheritdoc}
     */
    public function rules() {
        return [
            [['type', 'keytype', 'keyword', 'datetimes', 'store_id', 'settle_status', 'promotion', 'paymodes'], 'safe'],
        ];
    }

    /**
     * Creates data provider instance with search query applied
     * @return ActiveDataProvider
     */
    public function buildQuery() {
        $alias = 't';
        $query = static::find();
        $query->with([
            'user', 'unifiedOrder', 'address', 'trade', 'store'
        ]);
        if ($alias) {
            $query->alias($alias);
            $alias .= '.';
        }
        $this->bindFilterCondition($query, $alias);
        if ($this->store_id) {
            $query->andWhere([
                $alias . 'store_id' => $this->store_id
            ]);
        }
        $query->active();
        $this->bindKeywords($query, $alias);
        if (!empty($this->datetimes)) {
            list($beginDate, $endDate) = $this->datetimes;
            $query->andFilterDuration('t.created_at', Yii::$app->formatter->asTimestamp($beginDate), Yii::$app->formatter->asTimestamp($endDate));
        }
        $type = $this->type ?: 'default';
        $method = Inflector::variablize('bind_condition_' . $type);
        $handler = array($this, $method);
        if ($this->hasMethod($method) && is_callable($handler)) {
            call_user_func_array($handler, [$query, $alias]);
        }
        $query->debug();
        return $query;
    }

    /**
     * 全部订单
     * @param \common\db\ActiveQuery $query
     */
    protected function bindKeywords($query, $alias = 't') {
        $word = trim($this->keyword);
        if (!$word) {
            return;
        }
        $condition = [
            'or',
        ];
        if ($this->keytype == 'order_no') {
            $condition[] = [$alias . 'order_no' => $word];
            $query->innerJoinWith('unifiedOrder unified');
            $condition[] = ['unified.order_no' => $word];
        } elseif ($this->keytype == 'user_id') {
            $condition[] = [$alias . 'user_id' => $word];
        } elseif ($this->keytype == 'receiver') {
            $query->joinWith('address address');
            $condition[] = ['like', 'address.name', $word];
        } elseif ($this->keytype == 'receiver_mobile') {
            $query->joinWith('address address');
            $condition[] = ['like', 'address.mobile', $word];
        } elseif ($this->keytype == 'goods_name') {
            $query->joinWith('goods goods');
            $condition[] = ['like', 'goods.name', $word];
            $condition[] = ['like', 'goods.goods_name', $word];
        } else {
            $query->joinWith('goods goods');
            $query->joinWith('address address');
            if (StringHelper::isNumber($word)) {
                $condition[] = [$alias . 'user_id' => $word];
                $condition[] = [$alias . 'order_no' => $word];
                $condition[] = [$alias . 'trade_no' => $word];
                if (StringHelper::isMobile($word)) {
                    $condition[] = ['address.mobile' => $word];
                }
            } else {
                $condition = [
                    'or',
                    ['like', 'goods.name', $word],
                    ['like', 'address.name', $word],
                ];
            }
        }
        $query->andWhere($condition);
    }

    /**
     * 附加过滤条件
     * @param \common\db\ActiveQuery $query
     */
    protected function bindFilterCondition($query, $alias = 't.') {
        return $this;
    }

    /**
     * 默认订单
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionDefault($query, $alias = 't.') {
        return $this;
    }

    /**
     * 待付款
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionPayment($query, $alias = 't') {
        $query->innerJoinWith('unifiedOrder unified');
        $query->andWhere([
            'and',
            ['unified.status' => [self::STATUS_DEFAULT, self::STATUS_ACTIVE]],
            ['>', 'unified.created_at', time() - self::EXPIRED_DURTION],
            ['is', 'unified.trade_no', null],
            new Expression('unified.pay_time < unified.created_at')
        ]);
        $query->groupBy($alias . 'unified_id');
        return $this;
    }

    /**
     * 待发货
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionDeliver($query, $alias = 't') {
        $query->andWhere([
            't.status' => [
                self::STATUS_PAID,
                self::STATUS_SHIPPING,
                self::STATUS_SHIP,
            ]
        ]);
        $query->joinWith('goods goods');
        $query->joinWith('refund refund');
        $query->andWhere([
            'or',
            ['refund.id' => null],
            [
                'and',
                ['refund.deleted_at' => 0],
                ['>=', 'refund.status', ShopOrderRefund::STATUS_DEFAULT],
            ],
        ]);
//        $query->andWhere([
//            'goods.deliver_id' => 0
//        ]);
        $query->groupBy($alias . 'id');
        return $this;
    }

    /**
     * 已发货
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionShipped($query, $alias = 't') {
        $query->andWhere([
            $alias . 'status' => self::STATUS_SHIPPED,
        ]);
        return $this;
    }

    /**
     * 已收货
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionReceived($query, $alias = 't') {
        $query->andWhere([
            '>', $alias . 'status', self::STATUS_SHIPPED,
        ]);
        $query->joinWith('delivers delivers');
        $query->andWhere([
            '!=', 'delivers.received_at', 0,
        ]);
        $query->groupBy($alias . 'id');
        return $this;
    }

    /**
     * 已完成
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionFinish($query, $alias = 't') {
        $query->andWhere([
            'and',
            ['>=', $alias . 'status', self::STATUS_RECEIVED],
            ['is not', $alias . 'trade_no', null],
            new Expression($alias . 'pay_time >= ' . $alias . 'created_at')
        ]);
        $query->joinWith('delivers delivers');
        $query->andWhere([
            '!=', 'delivers.received_at', 0,
        ]);
        $query->groupBy($alias . 'id');
        return $this;
    }

    /**
     * 已关闭
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionClose($query, $alias = 't') {
        $query->innerJoinWith('unifiedOrder unified');
        $query->andWhere([
            'and',
            [
                'or',
                ['<', 'unified.status', 0],
                [
                    'and',
                    ['unified.status' => [self::STATUS_DEFAULT, self::STATUS_ACTIVE]],
                    ['<', 'unified.created_at', time() - self::EXPIRED_DURTION],
                ],
            ],
            ['unified.trade_no' => null],
            ['unified.pay_time' => 0],
        ]);
        $query->groupBy($alias . 'unified_id');
        return $this;
    }

    /**
     * 退款中
     * @param \common\db\ActiveQuery $query
     */
    protected function bindConditionRefund($query, $alias = 't') {
        $query->andWhere([
            'and',
            ['>=', $alias . 'status', self::STATUS_PAID],
            ['<', $alias . 'status', self::STATUS_RECEIVED],
        ]);
        $query->innerJoinWith('activeRefund refund');
//        $query->andWhere([
//            'and',
//            [
//                'or',
//                ['<', 'unified.status', 0],
//                [
//                    'and',
//                    ['unified.status' => [self::STATUS_DEFAULT, self::STATUS_ACTIVE]],
//                    ['<', 'unified.created_at', time() - self::EXPIRED_DURTION],
//                ],
//            ],
//            ['unified.trade_no' => null],
//            ['unified.pay_time' => 0],
//        ]);
//        $query->groupBy($alias . 'unified_id');
        return $this;
    }

}
